package com.young.lib_fragments.fms

import android.os.Bundle
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import com.young.lib_fragments.anim.DefaultFmTransactionAnim
import com.young.lib_fragments.anim.IFmTransactionAnim
import com.young.lib_fragments.fms.interfaces.IFmShowCompleted
import com.young.lib_fragments.fms.interfaces.IGetChildFragmentContainerId
import com.young.lib_fragments.fms.interfaces.IGetFragmentContainerId
import com.young.lib_fragments.fms.interfaces.ITransitions
import com.young.lib_fragments.utils.FmTransitionsUtil
import com.young.lib_fragments.utils.HandleExceptionBackStackUtil
import com.young.lib_fragments.utils.RegisterForActivityResultUtil

/**
 * @author huangzehui
 * @date 2025/1/10 12:53 周五
 * @description 基础的 fragment
 */
abstract class BaseFragment : Fragment(), IGetFragmentContainerId, IGetChildFragmentContainerId,
    ITransitions {

    // 返回监听
    private val mBackPressed = object : OnBackPressedCallback(false) {
        override fun handleOnBackPressed() {
            onBackPress()
        }
    }

    /**
     * Fragment 展示完成回调
     */
    internal var fmShowCompleted: IFmShowCompleted? = null

    /**
     * startActivityForResult 的替代方式辅助类
     */
    protected val registerForActivityResultUtil by lazy {
        RegisterForActivityResultUtil(lifecycle)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        HandleExceptionBackStackUtil.bindBackStackEntryId(getTargetFragmentManager(), this)

    }

    override fun onDestroyView() {
        super.onDestroyView()
        HandleExceptionBackStackUtil.unBindFragmentToBackStackEntry(getTargetFragmentManager(), this)
        removeTriggerFmShowCompletedTask()
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // 屏蔽Fragment的点击穿透
        view.setOnClickListener { }
        super.onViewCreated(view, savedInstanceState)
        initBackListener()
        delayTriggerFmShowCompleted()
    }

    override fun onPause() {
        super.onPause()
        removeTriggerFmShowCompletedTask()
    }

    override fun getFragmentContainerId(): Int {
        val ac = requireActivity()
        if (ac is IGetFragmentContainerId) {
            return ac.getFragmentContainerId()
        }
        throw Exception("please activity to impl IGetFragmentContainerId")
    }

    override fun getChildFragmentContainerId(): Int {
        return 0
    }

    /**
     * 初始化返回监听
     */
    private fun initBackListener() {
        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, mBackPressed)
    }

    /**
     * 返回触发监听
     */
    protected open fun onBackPress() {

    }

    /**
     * 设置是否响应返回监听
     *
     * @param enable true：当前fragment响应返回事件 false: 不响应返回事件
     *
     */
    protected fun setEnableBackPress(enable: Boolean) {
        mBackPressed.isEnabled = enable
    }


    // fragment 操作 start

    override fun start(
        fm: Fragment,
        args: Bundle?,
        isToBackStack: Boolean,
        toBackStackName: String?,
        fmTag: String?,
        fmTransactionAnim: IFmTransactionAnim?
    ) {
        args?.let {
            fm.arguments = it
        }

        FmTransitionsUtil.addFm(
            fmManager = getTargetFragmentManager(),
            containerViewId = getFragmentContainerId(),
            fm = fm,
            fmTag = fmTag,
            isToBackStack = isToBackStack,
            toBackStackName = toBackStackName,
            fmTransactionAnim = fmTransactionAnim ?: getDefaultFmTransactionAnim()
        )
    }

    override fun start(
        fmTransaction: FragmentTransaction,
        fm: Fragment,
        args: Bundle?,
        fmTag: String?,
        isToBackStack: Boolean,
        toBackStackName: String?,
        fmTransactionAnim: IFmTransactionAnim?
    ) {
        args?.let {
            fm.arguments = it
        }

        FmTransitionsUtil.addFm(
            fmManager = getTargetFragmentManager(),
            fmTransaction = fmTransaction,
            containerViewId = getFragmentContainerId(),
            fm = fm,
            fmTag = fmTag,
            isToBackStack = isToBackStack,
            toBackStackName = toBackStackName,
            fmTransactionAnim = fmTransactionAnim ?: getDefaultFmTransactionAnim()
        )
    }

    override fun startWithPopFm(
        fm: Fragment,
        args: Bundle?,
        lastFm: Fragment,
        fmTag: String?,
        isToBackStack: Boolean,
        toBackStackName: String?,
        fmTransactionAnim: IFmTransactionAnim?,
        showCompletedTime: Long
    ) {
        args?.let {
            fm.arguments = it
        }

        FmTransitionsUtil.addWithPopFm(
            fmManager = getTargetFragmentManager(),
            containerViewId = getFragmentContainerId(),
            fm = fm,
            lastFm = lastFm,
            fmTag = fmTag,
            isToBackStack = isToBackStack,
            toBackStackName = toBackStackName,
            fmTransactionAnim = fmTransactionAnim ?: getDefaultFmTransactionAnim(),
            showCompletedTime = showCompletedTime
        )
    }

    override fun pop() {
        FmTransitionsUtil.pop(getTargetFragmentManager())
    }

    override fun pop2Root() {
        FmTransitionsUtil.pop2Root(getTargetFragmentManager())
    }

    override fun pop2BackStackNameFm(toBackStackName: String, isInclude: Boolean) {
        FmTransitionsUtil.pop2BackStackNameFm(getTargetFragmentManager(), toBackStackName, isInclude)
    }

    override fun pop2IdFm(id: Int, isInclude: Boolean) {
        FmTransitionsUtil.pop2IdFm(getTargetFragmentManager(), id, isInclude)
    }

    override fun pop2TargetFmCls(fragmentCls: Class<out Fragment>, isInclude: Boolean) {
        FmTransitionsUtil.pop2TargetFmCls(getTargetFragmentManager(), fragmentCls, isInclude)
    }

    override fun removeFragment(fm: Fragment?) {
        FmTransitionsUtil.removeFragment(getTargetFragmentManager(), fm)
    }

    override fun show(
        fm: Fragment,
        args: Bundle?,
        fmTag: String?,
        fmTransactionAnim: IFmTransactionAnim?
    ) {
        FmTransitionsUtil.show(
            fmManager = getTargetFragmentManager(),
            containerViewId = getFragmentContainerId(),
            fm = fm,
            fmTag = fmTag,
            fmTransactionAnim = fmTransactionAnim ?: getDefaultFmTransactionAnim()
        )
    }

    override fun hide(fm: Fragment, fmTransactionAnim: IFmTransactionAnim?) {
        FmTransitionsUtil.hide(
            getTargetFragmentManager(),
            fm,
            fmTransactionAnim ?: getDefaultFmTransactionAnim()
        )
    }

    override fun showAndHide(
        showFm: Fragment,
        args: Bundle?,
        showFmTag: String?,
        hideFm: Fragment?,
        fmTransactionAnim: IFmTransactionAnim?
    ) {
        FmTransitionsUtil.showAndHide(
            fmManager = getTargetFragmentManager(),
            containerViewId = getFragmentContainerId(),
            showFm = showFm,
            showFmTag = showFmTag,
            hideFm = hideFm,
            fmTransactionAnim = fmTransactionAnim ?: getDefaultFmTransactionAnim()
        )
    }

    override fun getDefaultFmTransactionAnim(): IFmTransactionAnim {
        return DefaultFmTransactionAnim()
    }

    /**
     * 获取目标需要使用的fragmentManager
     */
    open fun getTargetFragmentManager(): FragmentManager {
        // activity那一级的FragmentManager（最通用的，viewpager2等都可以使用这个）
        return requireActivity().supportFragmentManager
        // 当前fragment的父级Fragment（非嵌套的时候，会等同于 requireActivity().supportFragmentManager，嵌套了就会不一致）
//        return parentFragmentManager
        // 当前fragment有嵌套fragment的时候，例如需要弹出dialogfragment等，可以使用这个
//        return childFragmentManager
    }

    // fragment 操作 end

    // 其他 start

    // 延时触发 IFmShowCompleted 回调 的任务
    private val mTriggerFmShowCompletedTask = Runnable {
        if (isAdded) {
            triggerFmShowCompleted()
        }
    }


    /**
     * 移除触发 IFmShowCompleted 回调 的任务
     */
    private fun removeTriggerFmShowCompletedTask() {
        view?.removeCallbacks(mTriggerFmShowCompletedTask)
    }

    /**
     *  延时触发 IFmShowCompleted 回调
     */
    private fun delayTriggerFmShowCompleted() {
        if (fmShowCompleted == null) {
            return
        }
        requireView().postDelayed(mTriggerFmShowCompletedTask, fmShowCompleted!!.getDelayMillis())
    }

    /**
     * 触发 IFmShowCompleted 回调
     */
    private fun triggerFmShowCompleted() {
        fmShowCompleted?.let {
            it.onShowCompleted()
            fmShowCompleted = null
        }
    }

    // 其他 end

}